#include "cpu.h"
#include "memory.h"
#include "operation.h"
#include "operationfactory.h"


CPU* CPU::instance = 0;

CPU::CPU(QObject* parent)
    :QObject(parent), memory(Memory::getInstance(this)), opFactory(OperationFactory::getInstance(memory, this, this))
{
    QString empty = QString("00000000000000000000000000000000");
    for(int i = 0; i < G_REGISTERS; i++)
    {
        registers[i] = empty;
    }
    IR = empty;
    PC = 0;
}

CPU::~CPU()
{
}

void CPU::setIR(const QString &value)
{
    Q_ASSERT(value.size() == 32);
    IR = value;
    emit registersChanged(ID_IR);
}

QString CPU::getIR() const
{
    return IR;
}

CPU* CPU::getInstance(QObject *parent)
{
    if(instance == 0)
    {
        instance = new CPU(parent);
    }
    return instance;
}

void CPU::setPC(quint32 pc)
{
    PC = pc;
    emit registersChanged(ID_PC);
}

void CPU::setRegisters(int index, const QString &content)
{
    Q_ASSERT(index >= 0 && index < G_REGISTERS);
    Q_ASSERT(content.size() == 32);
    registers[index] = content;
    emit registersChanged(index);
}

quint32 CPU::getPC() const
{
    return PC;
}

QString CPU::getRegister(int index) const
{
    return registers[index];
}

void CPU::exec()
{
    QString temp = QString();
    for(int i = 0; i < 4; i++)
    {
        temp.append(memory->read(PC + i));
    }
    setIR(temp);
    setPC(PC + 4);
    Operation* operation = opFactory->getOperation(IR);
    if(operation)
    {
        operation->exec(IR);
    }
}
